/*
 * Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
 * Copyright 2016-2017 NXP
 * All rights reserved.
 *
 * THIS SOFTWARE IS PROVIDED BY NXP "AS IS" AND ANY EXPRESSED OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL NXP OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */
/*!
 * @file lin.h
 *
 * @page misra_violations MISRA-C:2012 violations
 *
 * @section [global]
 * Violates MISRA 2012 Advisory Directive 4.9, A function should be used in preference to a function-like
 * macro where they are interchangeable.
 * The macro is defined for callback functions or use for skeleton code.
 * This way is more efficient.
 *
 * @section [global]
 * Violates MISRA 2012 Advisory Rule 8.9, An object should be defined at block scope if its identifier
 * only appears in a single function.
 * Since array g_lin_hardware_ifc and timerGetTimeIntervalCallbackArr are defined and
 * initialized into lin_cfg.c and this file is generated by NCF tool cannot be placed
 * elsewhere.
 */


#ifndef LIN_H
#define LIN_H

/*!
 * @addtogroup lowlevel_group
 * @{
 */
#include "lin_types.h"
#include "lin_cfg.h"
#include "lin_driver.h"


/*******************************************************************************
 * Definitions
 ******************************************************************************/
/* This macro is used only when transport layer is not used;
remove '#if' directive if needed it also when transport layer is enabled */
#if ((1U != SUPPORT_TRANSPORT_LAYER) || (1U != SUPPORT_DIAG_SERVICE))
#define UNUSED(x)   (void)(x)
#endif /* ((1U != SUPPORT_TRANSPORT_LAYER) || (1U != SUPPORT_DIAG_SERVICE)) */

/* Define diagnostic services id */
#define SERVICE_ASSIGN_NAD                0xB0U      /*!< Assign NAD service */
#define SERVICE_ASSIGN_FRAME_ID           0xB1U      /*!< Assign frame id service */
#define SERVICE_READ_BY_IDENTIFY          0xB2U      /*!< Read by identify service */
#define SERVICE_CONDITIONAL_CHANGE_NAD    0xB3U      /*!< Conditional change NAD service */
#define SERVICE_SAVE_CONFIGURATION        0xB6U      /*!< Save configuration service */
#define SERVICE_ASSIGN_FRAME_ID_RANGE     0xB7U      /*!< Assign frame id range service */

#define SERVICE_READ_DATA_BY_IDENTIFY     0x22U      /*!< Service read data by identifier */
#define SERVICE_WRITE_DATA_BY_IDENTIFY    0x2EU      /*!< Service write data by identifier */
#define SERVICE_SESSION_CONTROL           0x10U      /*!< Service session control */
#define SERVICE_IO_CONTROL_BY_IDENTIFY    0x2FU      /*!< Service I/O control */
#define SERVICE_FAULT_MEMORY_READ         0x19U      /*!< Service fault memory read */
#define SERIVCE_FAULT_MEMORY_CLEAR        0x14U      /*!< Service fault memory clear */

/* Define PCI request services */
#define PCI_SAVE_CONFIGURATION            0x01U      /*!< PCI value save configuration */

/* Define PCI response's services */
#define PCI_RES_READ_BY_IDENTIFY          0x06U      /*!< PCI response value read by identify */
#define PCI_RES_SAVE_CONFIGURATION        0x01U      /*!< PCI response value save configuration */
#define PCI_RES_ASSIGN_FRAME_ID_RANGE     0x01U      /*!< PCI response value assign frame id range */

/* Identifier user defined */
#define LIN_READ_USR_DEF_MIN              32U       /*!< Min user defined */
#define LIN_READ_USR_DEF_MAX              63U       /*!< Max user defined */

/* Identification */
#define LD_NEGATIVE_RESPONSE              0x53U      /*!< Negative response */
#define LD_POSITIVE_RESPONSE              0x54U      /*!< Positive response */

/* Low level API return values */
#define LIN_LLD_OK                        0x00U     /*!< Return value is OK */
#define LIN_LLD_ERROR                     0xFFU     /*!< Return value is ERROR */

/*!
 * @brief PDU data.
 * Implements : lin_tl_pdu_data_t_Class
 */
typedef l_u8 lin_tl_pdu_data_t[8];

/*******************************************************************************
 * LOW LEVEL DRIVER
 ******************************************************************************/

/*!
 * @brief Event id
 * Implements : lin_lld_event_id_t_Class
 */
typedef enum
{
    LIN_LLD_PID_OK                  = 0x00U,    /*!< LIN_LLD_PID_OK */
    LIN_LLD_TX_COMPLETED            = 0x01U,    /*!< LIN_LLD_TX_COMPLETED */
    LIN_LLD_RX_COMPLETED            = 0x02U,    /*!< LIN_LLD_RX_COMPLETED */
    LIN_LLD_PID_ERR                 = 0x03U,    /*!< LIN_LLD_PID_ERR */
    LIN_LLD_FRAME_ERR               = 0x04U,    /*!< LIN_LLD_FRAME_ERR */
    LIN_LLD_CHECKSUM_ERR            = 0x05U,    /*!< LIN_LLD_CHECKSUM_ERR */
    LIN_LLD_READBACK_ERR            = 0x06U,    /*!< LIN_LLD_READBACK_ERR */
    LIN_LLD_NODATA_TIMEOUT          = 0x07U,    /*!< No data timeout or received part of data but not completed */
    LIN_LLD_BUS_ACTIVITY_TIMEOUT    = 0x08U     /*!< LIN_LLD_BUS_ACTIVITY_TIMEOUT */
} lin_lld_event_id_t;

/*******************************************************************************
 * Protocol
 ******************************************************************************/
/*!
 * @brief List of protocols
 * Implements : lin_protocol_handle_t_Class
 */
typedef enum
{
    LIN_PROTOCOL_21     = 0x00U,    /*!< LIN protocol version 2.1, 2.2 */
    LIN_PROTOCOL_J2602  = 0x01U,    /*!< J2602 protocol */
    LIN_PROTOCOL_13     = 0x02U,    /*!< LIN protocol version 1.3 */
    LIN_PROTOCOL_20     = 0x03U     /*!< LIN protocol version 2.0 */
} lin_protocol_handle_t;

/*!
 * @brief List of diagnostic classes
 * Implements : lin_diagnostic_class_t_Class
 */
typedef enum
{
    LIN_DIAGNOSTIC_CLASS_I      = 0x01U,    /*!< LIN Diagnostic Class 1 */
    LIN_DIAGNOSTIC_CLASS_II     = 0x02U,    /*!< LIN Diagnostic Class 2*/
    LIN_DIAGNOSTIC_CLASS_III    = 0x03U     /*!< LIN Diagnostic Class 3 */
} lin_diagnostic_class_t;

/*!
 * @brief status of LIN bus
 * Implements : lin_word_status_str_t_Class
 */
typedef struct
{
    unsigned int error_in_res                  : 1;        /*!< Error in response */
    unsigned int successful_transfer           : 1;        /*!< Successful transfer */
    unsigned int overrun                       : 1;        /*!< Overrun */
    unsigned int go_to_sleep_flg               : 1;        /*!< Goto sleep */
    unsigned int bus_activity                  : 1;        /*!< Bus activity */
    unsigned int event_trigger_collision_flg   : 1;        /*!< Event trigger collision */
    unsigned int save_config_flg               : 1;        /*!< Save configuration */
    unsigned int reserved                      : 1;        /*!< Dummy */
    unsigned int last_pid                      : 8;        /*!< Last PID */
} lin_word_status_str_t;

/*******************************************************************************
 * Interfaces
 ******************************************************************************/
/*! @brief Mode of LIN node (master or slave) */
#define    LIN_SLAVE  0    /*!< Slave node */
#define    LIN_MASTER 1    /*!< Master node */

/*******************************************************************************
 * General
 ******************************************************************************/
/*!
 * @brief Serial number
 * Implements : lin_serial_number_t_Class
 */
typedef struct
{
    l_u8 serial_0;  /*!< Serial 0 */
    l_u8 serial_1;  /*!< Serial 1 */
    l_u8 serial_2;  /*!< Serial 2 */
    l_u8 serial_3;  /*!< Serial 3 */
} lin_serial_number_t;

/*!
 * @brief Attributes of LIN node
 * Implements : lin_node_attribute_t_Class
 */
typedef struct
{
    l_u8                    *configured_NAD_ptr;        /*!< NAD value used in configuration command */
    l_u8                    initial_NAD;                /*!< Initial NAD */
    lin_product_id_t        product_id;                 /*!< Product ID */
    lin_serial_number_t     serial_number;              /*!< Serial number */
    l_u8                    *resp_err_frm_id_ptr;       /*!< List index of frame contain response error signal */
    l_u8                    num_frame_have_esignal;     /*!< Number of frame contain error signal */
    l_signal_handle         response_error;             /*!< Signal used to update response error */
    l_u16*                  response_error_byte_offset_ptr; /*!< Byte offset of response error signal */
    l_u8*                   response_error_bit_offset_ptr;  /*!< Bit offset of response error signal */
    l_u8                    num_of_fault_state_signal;  /*!< Number of Fault state signal */
    const l_signal_handle   *fault_state_signal_ptr;    /*!< List of fault state signal */
    l_u16                   P2_min;                     /*!< P2 min */
    l_u16                   ST_min;                     /*!< ST min */
    l_u16                   N_As_timeout;               /*!< N_As_timeout */
    l_u16                   N_Cr_timeout;               /*!< N_Cr_timeout */
    l_u8                    number_support_sid;         /*!< Number of supported  diagnostic services */
    const l_u8              *service_supported_ptr;     /*!< List of supported diagnostic service */
    l_u8                    *service_flags_ptr;         /*!< List of associated flags with supported diagnostic services */
} lin_node_attribute_t;

/*******************************************************************************
 * Frame
 ******************************************************************************/
/*!
 * @brief Types of frame
 * Implements : lin_frame_type_t_Class
 */
typedef enum
{
    LIN_FRM_UNCD  = 0x00U,  /*!< Unconditional frame */
    LIN_FRM_EVNT  = 0x01U,  /*!< Event triggered frame */
    LIN_FRM_SPRDC = 0x10U,  /*!< Sporadic frame */
    LIN_FRM_DIAG  = 0x11U   /*!< Diagnostic frame */
} lin_frame_type_t;

/*!
 * @brief LIN frame response
 * Implements : lin_frame_response_t_Class
 */
typedef enum
{
    LIN_RES_PUB     = 0x00U,    /*!< Publisher response */
    LIN_RES_SUB     = 0x01U     /*!< Subscriber response */
} lin_frame_response_t;

/*!
 * @brief Informations of associated frame
 * Implements : lin_associate_frame_t_Class
 */
typedef struct
{
    l_u8 num_of_associated_uncond_frames;               /*!< Number of associated unconditional frame ID */
    const l_frame_handle * associated_uncond_frame_ptr; /*!< Associated unconditional frame ID */
    l_u8 coll_resolv_schd;                              /*!< Collision resolver index in the schedule table, used in event trigger frame case MASTER */
} lin_associate_frame_t;

/*!
 * @brief Frame description structure
 * Implements : lin_frame_t_Class
 */
typedef struct
{
    lin_frame_type_t               frm_type;         /*!< Frame information (unconditional or event triggered..) */
    l_u8                           frm_len;          /*!< Length of the frame */
    lin_frame_response_t           frm_response;     /*!< Action response when received PID */
    l_u16                          frm_offset;       /*!< Frame byte offset in frame buffer */
    l_u16                          flag_offset;      /*!< Flag byte offset in flag buffer */
    l_u8                           flag_size;        /*!< Flag size in flag buffer */
    const lin_associate_frame_t    *frame_data_ptr;  /*!< List of Signal to which the frame is associated and its offset */
} lin_frame_t;

/*******************************************************************************
 * Schedule table
 ******************************************************************************/
/*!
 * @brief LIN transport layer queue
 * Implements : lin_tl_queue_t_Class
 */
typedef l_u8 lin_tl_queue_t[8];

/*!
 * @brief Types of schedule tables
 * Implements : lin_sch_tbl_type_t_Class
 */
typedef enum
{
    LIN_SCH_TBL_NULL        = 0x00U,   /*!< Run nothing */
    LIN_SCH_TBL_NORM        = 0x01U,   /*!< Normal schedule table */
    LIN_SCH_TBL_DIAG        = 0x02U,   /*!< Diagnostic schedule table */
    LIN_SCH_TBL_GO_TO_SLEEP = 0x03U,   /*!< Goto sleep schedule table */
    LIN_SCH_TBL_COLL_RESOLV = 0x04U    /*!< Collision resolving schedule table */
} lin_sch_tbl_type_t;

/*!
 * @brief LIN schedule structure
 * Implements : lin_schedule_data_t_Class
 */
typedef struct
{
    l_frame_handle      frm_id;         /*!< Frame ID, in case of unconditional or event triggered frame. For sporadic frame the value will be 0 (zero) */
    l_u8                delay_integer;  /*!< Actual slot time in INTEGER for one frame */
    lin_tl_queue_t        tl_queue_data;  /*!< Data used in case of diagnostic or configuration frame */
} lin_schedule_data_t;

/*!
 * @brief Schedule table description
 * Implements : lin_schedule_t_Class
 */
typedef struct
{
    l_u8                        num_slots;         /*!< Number of frame slots in the schedule table */
    lin_sch_tbl_type_t          sch_tbl_type;      /*!< Schedule table type */
    const lin_schedule_data_t   *ptr_sch_data_ptr; /*!< Address of the schedule table */
} lin_schedule_t;

/*******************************************************************************
 * Transport Layer / Diagnostic
 ******************************************************************************/
/*!
 * @brief Diagnostic mode
 * Implements : l_diagnostic_mode_t_Class
 */
typedef enum
{
    DIAG_NONE               = 0x00U,    /*!< None */
    DIAG_INTERLEAVE_MODE    = 0x01U,    /*!< Interleave mode */
    DIAG_ONLY_MODE          = 0x02U     /*!< Diagnostic only mode */
} l_diagnostic_mode_t;

/*!
 * @brief Status of the last configuration call for LIN 2.1
 * Implements : lin_service_status_t_Class
 */
typedef enum
{
    LD_SERVICE_BUSY         = 0x00U,    /*!< Service is ongoing */
    LD_REQUEST_FINISHED     = 0x01U,    /*!< The configuration request has been completed */
    LD_SERVICE_IDLE         = 0x02U,    /*!< The configuration request/response combination has been completed */
    LD_SERVICE_ERROR        = 0x03U     /*!< The configuration request or response experienced an error */
} lin_service_status_t;

/*!
 * @brief Status of the last configuration call completed
 * Implements : lin_last_cfg_result_t_Class
 */
typedef enum
{
    LD_SUCCESS              = 0x00U,    /*!< The service was successfully carried out */
    LD_NEGATIVE             = 0x01U,    /*!< The service failed, more information can be found by parsing error_code */
    LD_NO_RESPONSE          = 0x02U,    /*!< No response was received on the request */
    LD_OVERWRITTEN          = 0x03U     /*!< The slave response frame has been overwritten by another operation */
} lin_last_cfg_result_t;

/*!
 * @brief Transport layer event IDs
 * Implements : lin_tl_event_id_t_Class
 */
typedef enum
{
    TL_MAKE_RES_DATA           = 0x00U, /*!< Make master request data */
    TL_SLAVE_GET_ACTION        = 0x01U, /*!< Get slave action */
    TL_TX_COMPLETED            = 0x02U, /*!< Transmit completed */
    TL_RX_COMPLETED            = 0x03U, /*!< Receive completed */
    TL_ERROR                   = 0x04U, /*!< Transport error */
    TL_TIMEOUT_SERVICE         = 0x05U, /*!< Transmit timeout */
    TL_HANDLER_INTERLEAVE_MODE = 0x06U, /*!< Interleave mode */
    TL_RECEIVE_MESSAGE         = 0x07U  /*!< Return data for ld_receive_message function */
} lin_tl_event_id_t;

/*!
 * @brief Transport layer event IDs
 * Implements : lin_tl_callback_return_t_Class
 */
typedef enum
{
    TL_ACTION_NONE      = 0x00U,     /*!< Default return value of call back function */
    TL_ACTION_ID_IGNORE = 0x01U      /*!< Ignore this ID */
} lin_tl_callback_return_t;

extern lin_tl_callback_return_t lin_tl_callback_handler(l_ifc_handle iii,
                                                        lin_tl_event_id_t tl_event_id,
                                                        l_u8 id);

#define LIN_TL_CALLBACK_HANDLER(iii, tl_event_id, id) lin_tl_callback_handler((iii), (tl_event_id), (id))
/* ---------------------- Transport layer multi frames ---------------------- */
/*!
 * @brief Status of queue
 * Implements : ld_queue_status_t_Class
 */
typedef enum
{
    LD_NO_DATA              = 0x00U,    /*!< Rx Queue is empty, has no data */
    LD_DATA_AVAILABLE       = 0x01U,    /*!< Data in queue is available */
    LD_RECEIVE_ERROR        = 0x02U,    /*!< Receive data is error for LIN21 and above*/
    LD_QUEUE_FULL           = 0x03U,    /*!< The queue is full */
    LD_QUEUE_AVAILABLE      = 0x04U,    /*!< Queue is available for insert data for LIN21 and above*/
    LD_QUEUE_EMPTY          = 0x05U,    /*!< Tx Queue is empty */
    LD_TRANSMIT_ERROR       = 0x06U,    /*!< Error while transmitting for LIN21 and above */
    LD_TRANSFER_ERROR       = 0x07U     /*!< Error while transmitting/receiving for LIN20 and J2602 */
} ld_queue_status_t;

/*!
 * @brief Status of LIN message
 * Implements : lin_message_status_t_Class
 */
typedef enum
{
    LD_NO_MSG               = 0x00U,    /*!< No message */
    LD_IN_PROGRESS          = 0x01U,    /*!< In progress */
    LD_COMPLETED            = 0x02U,    /*!< Completed */
    LD_FAILED               = 0x03U,    /*!< Failed */
    LD_N_AS_TIMEOUT         = 0x04U,    /*!< N_As timeout */
    LD_N_CR_TIMEOUT         = 0x05U,    /*!< N_Cr timeout */
    LD_WRONG_SN             = 0x06U     /*!< Wrong sequence number */
} lin_message_status_t;

/*!
 * @brief LIN diagnostic state
 * Implements : lin_diagnostic_state_t_Class
 */
typedef enum
{
    LD_DIAG_IDLE                = 0x01U,    /*!< IDLE */
    LD_DIAG_TX_PHY              = 0x02U,    /*!< Diagnostic transmit physical */
    LD_DIAG_TX_FUNCTIONAL       = 0x03U,    /*!< Diagnostic transmit active */
    LD_DIAG_TX_INTERLEAVED      = 0x04U,    /*!< Diagnostic transmit in interleave mode */
    LD_DIAG_RX_PHY              = 0x05U,    /*!< Diagnostic receive in physical */
    LD_DIAG_RX_FUNCTIONAL       = 0x06U,    /*!< Diagnostic receive functional request */
    LD_DIAG_RX_INTERLEAVED      = 0x07U     /*!< Diagnostic receive in interleave mode */
} lin_diagnostic_state_t;

/*!
 * @brief Types of message timeout
 * Implements : lin_message_timeout_type_t_Class
 */
typedef enum
{
    LD_NO_CHECK_TIMEOUT      = 0x00U,   /*!< No check timeout */
    LD_CHECK_N_AS_TIMEOUT    = 0x01U,   /*!< check N_As timeout */
    LD_CHECK_N_CR_TIMEOUT    = 0x02U    /*!< check N_Cr timeout */
} lin_message_timeout_type_t;

/*!
 * @brief Transport layer queue
 * Implements : lin_transport_layer_queue_t_Class
 */
typedef struct
{
    l_u16                     queue_header;             /*!< The first element of queue */
    l_u16                     queue_tail;               /*!< The last element of queue */
    ld_queue_status_t         queue_status;             /*!< Status of queue */
    l_u16                     queue_current_size;       /*!< Current size */
    l_u16                     queue_max_size;           /*!< Maximum size */
    lin_tl_pdu_data_t           *tl_pdu_ptr;              /*!< PDU data */
} lin_transport_layer_queue_t;

#define INTERLEAVE_MAX_TIMEOUT (l_u16)(1000000U/TIME_OUT_UNIT_US)      /*!< Slave node interleaved diagnostic response timeout */

/*!
 * @brief State of diagnostic interleaved mode
 * Implements : diag_interleaved_state_t_Class
 */
typedef enum
{
    DIAG_NOT_START          = 0x00U,    /*!< Not into slave response schedule with interleaved mode */
    DIAG_NO_RESPONSE        = 0x01U,    /*!< Master send 0x3D but slave does not response */
    DIAG_RESPONSE           = 0x02U     /*!< Response receive */
} diag_interleaved_state_t;

/*!
 * @brief Transport layer description
 * Implements : lin_tl_descriptor_t_Class
 */
typedef struct
{
    /* Declaration for both Master and Slave interface */
    lin_transport_layer_queue_t   tl_tx_queue;                /*!< Pointer to transmit queue on TL */
    lin_transport_layer_queue_t   tl_rx_queue;                /*!< Pointer to receive queue on TL */

    /* Declaration only for Master interface */
    /* message information in transmit queue */
    lin_message_status_t          rx_msg_status;              /*!< Cooked rx status */
    l_u16                         rx_msg_size;                /*!< Size of message in queue */

    /* message information in receive queue */
    lin_message_status_t          tx_msg_status;              /*!< Cooked tx status */
    l_u16                         tx_msg_size;                /*!< Size of message in queue */

    lin_last_cfg_result_t         last_cfg_result;            /*!< Status of the last configuration service */
    l_u8                          last_RSID;                  /*!< RSID of the last node configuration service */
    l_u8                          ld_error_code;              /*!< Error code in case of positive response */

    lin_message_timeout_type_t    check_timeout_type;         /*!< Timeout type */
    l_u16                         check_timeout;              /*!< Timeout counter for N_As and N_Cr timeout */
    lin_product_id_t              *product_id_ptr;            /*!< To store address of RAM area contain response */
    l_u8                          num_of_pdu;                 /*!< Number of received pdu */
    l_u8                          frame_counter;              /*!< Frame counter in received message */
    lin_diagnostic_state_t        diag_state;                 /*!< Diagnostic state */
    diag_interleaved_state_t      diag_interleave_state;      /*!< state of diagnostic interleaved mode */
    l_u16                         interleave_timeout_counter; /*!< Interleaved timeout counter */
    l_u8                          slave_resp_cnt;             /*!< Slave Response data counter */
    lin_service_status_t          service_status;             /*!< Status of the last configuration service */

    bool                          ld_return_data;             /*!< Decide return data of diagnostic frame to pointer of ld_receive_message function */
    bool                          FF_pdu_received;            /*!< Status of FF pdu */

    /* Pointer use to ld_receive_message funtion */
    l_u8* receive_message_ptr;                                /*!< Pointer to receive_message array of user */
    l_u8* receive_NAD_ptr;                                    /*!< Pointer to receive_NAD of user */
    l_u16* receive_message_length_ptr;                        /*!< Pointer to receive_message_length of user */
} lin_tl_descriptor_t;

/*******************************************************************************
 * Configuration
 ******************************************************************************/
/*!
 * @brief Configuration structure
 * Implements : lin_protocol_user_config_t_Class
 */
typedef struct
{
    lin_protocol_handle_t       protocol_version;   /*!< Protocol version */
    lin_protocol_handle_t       language_version;   /*!< Language version */
    lin_diagnostic_class_t      diagnostic_class;   /*!< Diagnostic class */
    bool                        function;           /*!< Function LIN_MASTER or LIN_SLAVE_) */
    /* Protocol */
    l_u8                        number_of_configurable_frames;      /*!< Number of frame except diagnostic frames */
    l_u8                        frame_start;                        /*!< Start index of frame list */
    const lin_frame_t           *frame_tbl_ptr;                     /*!< Frame list except diagnostic frames */

    const l_u16                 *list_identifiers_ROM_ptr; /*!< Configuration in ROM */
    l_u8                        *list_identifiers_RAM_ptr; /*!< Configuration in RAM */
    l_u16                       max_idle_timeout_cnt;      /*!< Max Idle timeout counter */
    l_u8                        num_of_schedules;          /*!< Number of schedule table */
    l_u8                        schedule_start;            /*!< Start index of schedule table list */
    const lin_schedule_t        *schedule_tbl;             /*!< Schedule table list */
    l_ifc_slave_handle          slave_ifc_handle;          /*!< Interface handler of slave node */
    l_ifc_master_handle         master_ifc_handle;         /*!< Interface handler of master node */
    lin_user_config_t           *lin_user_config_ptr;      /*!< Pointer to LIN driver user configuration structure */
#if (1U == SUPPORT_TRANSPORT_LAYER)
    lin_tl_pdu_data_t           *tl_tx_queue_data_ptr; /*!< Tx queue data */
    lin_tl_pdu_data_t           *tl_rx_queue_data_ptr; /*!< Rx queue data */
    l_u16                       max_message_length;    /*!< Max message length*/
#endif /* (1U == SUPPORT_TRANSPORT_LAYER) */
} lin_protocol_user_config_t;

/*!
 * @brief LIN master configuration structure
 * Implements : lin_master_data_t_Class
 */
typedef struct
{
    l_u8                 active_schedule_id;         /*!< Active schedule table id */
    l_u8                 previous_schedule_id;       /*!< Previous schedule table id */
    l_u8                 *schedule_start_entry_ptr;  /*!< Start entry of each schedule table */
    l_bool               event_trigger_collision_flg;/*!< Flag trigger collision event */
    l_u8                 master_data_buffer[8];      /*!< Master data buffer */
    l_u16                frm_offset;                 /*!< Frame offset */
    l_u8                 frm_size;                   /*!< Size of frame */
    l_u16                flag_offset;                /*!< Flag offset */
    l_u8                 flag_size;                  /*!< Flag size */
    l_bool               send_slave_res_flg;         /*!< Flag to send Slave Response Schedule */
    l_bool               send_functional_request_flg;/*!< Flag send Functional Request */
} lin_master_data_t;

/*!
 * @brief LIN protocol status structure
 * Implements : lin_protocol_state_t_Class
 */
typedef struct
{
    /* LIN data pointer */
    l_u16                  baud_rate;             /*!< Adjusted baud rate */
    l_u8                   *response_buffer_ptr;  /*!< Response buffer */
    l_u8                   response_length;       /*!< Response length  */
    l_u8                   successful_transfer;   /*!< Transfer flag */
    l_u8                   error_in_response;     /*!< Error response */
    l_bool                 go_to_sleep_flg;       /*!< Go to sleep flag */
    l_u8                   current_id;            /*!< Current PID */
    l_u8                   last_pid;              /*!< Last PID */
    l_u8                   num_of_processed_frame;/*!< Number of processed frames */
    l_u8                   overrun_flg;           /*!< overrun flag */
    lin_word_status_str_t  word_status;           /*!< Word status */
    l_u8                   next_transmit_tick;    /*!< Used to count the next transmit tick */
    l_bool                 save_config_flg;       /*!< Set when save configuration request has been received */
    l_diagnostic_mode_t    diagnostic_mode;       /*!< Diagnostic mode */
    l_u16                  frame_timeout_cnt;     /*!< Frame timeout counter for monitoring if timeout occurs during data transferring */
    l_u16                  idle_timeout_cnt;      /*!< Idle timeout counter */
    l_bool                 transmit_error_resp_sig_flg; /*!< Flag indicates that the error response signal is going to be sent */
} lin_protocol_state_t;
/* End of data definition */

/*******************************************************************************
 * Extern function
 ******************************************************************************/
extern l_u8 ld_read_by_id_callout(l_ifc_handle iii,
                                  l_u8 id,
                                  l_u8 * data);

/*******************************************************************************
 * Extern variables
 ******************************************************************************/
#if (1U == SUPPORT_SLAVE_MODE)
extern const lin_node_attribute_t           g_lin_node_attribute_array[LIN_NUM_OF_SLAVE_IFCS];
#endif /* (1U == SUPPORT_SLAVE_MODE) */

#if (1U == SUPPORT_MASTER_MODE)
extern lin_master_data_t                    g_lin_master_data_array[LIN_NUM_OF_MASTER_IFCS];
#endif /* (1U == SUPPORT_MASTER_MODE) */

extern lin_tl_descriptor_t                  g_lin_tl_descriptor_array[LIN_NUM_OF_IFCS];
extern const lin_protocol_user_config_t     g_lin_protocol_user_cfg_array[LIN_NUM_OF_IFCS];
extern lin_protocol_state_t                 g_lin_protocol_state_array[LIN_NUM_OF_IFCS];
extern volatile l_u8                        g_lin_frame_data_buffer[LIN_FRAME_BUF_SIZE];
extern volatile l_u8                        g_lin_flag_handle_tbl[LIN_FLAG_BUF_SIZE];
extern volatile l_bool                      g_lin_frame_flag_handle_tbl[LIN_NUM_OF_FRMS];
extern const l_u32                          g_lin_virtual_ifc[LIN_NUM_OF_IFCS];
extern const l_ifc_handle                   g_lin_hardware_ifc[HARDWARE_INSTANCE_COUNT];
extern const lin_timer_get_time_interval_t  timerGetTimeIntervalCallbackArr[LIN_NUM_OF_IFCS];
extern volatile l_u8                        g_buffer_backup_data[8];
extern volatile l_u8                        g_lin_frame_updating_flag_tbl[LIN_NUM_OF_FRMS];


/*******************************************************************************
 * Static functions
 ******************************************************************************/
/*!
 * @brief Computes maximum header timeout
 *
 * Theader_Maximum = 1.4 * THeader_Nominal, THeader_Nominal = 34 * TBit,
 * (13 nominal bits of break;   1 nominal bit of break delimiter; 10 bits for SYNC and 10 bits of PID)
 * TIME_OUT_UNIT_US is in micro second
 *
 * @param[in] baudRate LIN network baud rate
 * @return    maximum timeout for the selected baud rate
 *
 * Implements : lin_calc_max_header_timeout_cnt_Activity
 */
static inline l_u16 lin_calc_max_header_timeout_cnt(l_u32 baudRate)
{
    return (l_u16)((14U * 34U * 100000U / (TIME_OUT_UNIT_US * baudRate)) + 1U);
}

/*!
 * @brief Computes the maximum response timeout
 *
 * TResponse_Maximum = 1.4 * TResponse_Nominal, TResponse_Nominal = 10 * (NData+ 1) * TBit
 *
 * @param[in] baudRate LIN network baud rate
 * @param[in] size     frame size in bytes
 * @return maximum response timeout for the given baud rate and frame size
 *
 * Implements : lin_calc_max_res_timeout_cnt_Activity
 */
static inline l_u16 lin_calc_max_res_timeout_cnt(l_u32 baudRate,
                                                 l_u8 size)
{
    l_u16 a = (l_u16)(14U * (1U + (l_u16)size));

    return (l_u16)((a * 1000000U / (TIME_OUT_UNIT_US * baudRate)) + 1U);
}

/*******************************************************************************
 * Global functions
 ******************************************************************************/
/*!
 * @brief Makes or checks parity bits. If action is checking parity, the function
 * returns ID value if parity bits are correct or 0xFF if parity bits are incorrect. If action
 * is making parity bits, then from input value of ID, the function returns PID.
 *
 * @param pid PID byte in case of checking parity bits or ID byte in case of making parity bits.
 * @param typeAction TRUE for Checking parity bits, FALSE for making parity bits
 * @return 0xFF if parity bits are incorrect, ID in case of checking parity bits and
 * they are correct. Function returns PID in case of making parity bits.
 */
l_u8 lin_process_parity(l_u8 pid,
                        l_u8 typeAction);

/*!
 * @brief Callback handler for low level events
 *
 * This callback handler is being called from the LIN driver callback
 *
 * @param[in] iii LIN interface that is being handled
 * @param[in] event_id  Low level event id #lin_lld_event_id_t
 * @param[in] id Current protected identifier under processing by driver
 */
extern void lin_pid_resp_callback_handler(l_ifc_handle iii,
                                          const lin_lld_event_id_t event_id,
                                          l_u8 id);

/*!
 * @brief CALLBACK_HANDLER.
 *
 * @note call lin_pid_resp_callback_handler() function in MASTER mode
 */
#define CALLBACK_HANDLER(iii, event_id, id) lin_pid_resp_callback_handler((iii), (event_id), (id))

/*!
 * @brief This function initializes a LIN hardware instance for operation.
 * This function will initialize the run-time state structure to keep track of
 * the on-going transfers, initialize the module to user defined settings and
 * default settings, configure the IRQ state structure and enable the module-level
 * interrupt to the core, and enable the LIN hardware module transmitter and receiver.
 *
 * @param[in] iii LIN interface that is being handled
 * @return zero if the initialization was successful and non-zero if failed
 */
l_bool lin_lld_init(l_ifc_handle iii);

/*!
 * @brief This function disconnect the node from the cluster and
 *  free all hardware used
 *
 * @param[in] iii LIN interface that is being handled
 * @return Zero for success
 * @return void
 */
void lin_lld_deinit(l_ifc_handle iii);

/*!
 * @brief Enable the interrupt related to the interface
 *
 * @param[in] iii LIN interface that is being handled
 * @return Zero for success
 * @return Non-zero for error
 */
l_u8 lin_lld_int_enable(l_ifc_handle iii);

/*!
 * @brief Disable the interrupt related to the interface
 *
 * @param[in] iii LIN interface that is being handled
 * @return Zero for success
 * @return Non-zero for error
 */
l_u8 lin_lld_int_disable(l_ifc_handle iii);

/*!
 * @brief This function gets current state of an interface
 *
 * @param[in] iii LIN interface that is being handled
 * @return current LIN node state
 */
lin_node_state_t lin_lld_get_state(l_ifc_handle iii);

/*!
 * @brief This function sends frame header for the input PID.
 *
 * This function only initializes the sending of break field and then return.
 * Then the sync byte and PID will be sent in the interrupt handler of LIN interface.
 * @param[in] iii LIN interface that is being handled
 * @param[in] id ID of the header to be sent
 * @return Zero for success
 * @return Non-zero for error
 */
l_u8 lin_lld_tx_header(l_ifc_handle iii,
                       l_u8 id);

/*!
 * @brief This function send a wakeup signal
 *
 * @param[in] iii LIN interface that is being handled
 * @return Zero for success
 * @return Non-zero for error
 */
l_u8 lin_lld_tx_wake_up(l_ifc_handle iii);

/*!
 * @brief This function terminates an on-going data transmission/reception.
 *
 * @param[in] iii LIN interface that is being handled
 * @return Zero for success
 * @return Non-zero for error
 */
l_u8 lin_lld_ignore_response(l_ifc_handle iii);

/*!
 * @brief Let the low level driver go to low power mode
 *
 * @param[in] iii LIN interface that is being handled
 * @return Zero for success
 * @return Non-zero for error
 */
l_u8 lin_lld_set_low_power_mode(l_ifc_handle iii);

/*!
 * @brief This function sends frame data that is contained in LIN_lld_response_buffer[iii].
 *
 * This function will send the first data byte in the buffer and then return.
 * Next data bytes will be sent in the interrupt handler of LIN interface.
 * This function returns zero if sending of first data byte was successful.
 * @param[in] iii LIN interface that is being handled
 * @param[in] response_length Length of response
 * @return Zero for success
 * @return Non-zero for error
 */
l_u8 lin_lld_set_response(l_ifc_handle iii,
                          l_u8 response_length);

/*!
 * @brief This function receives frame data into the LIN_lld_response_buffer[iii] buffer.
 *
 * This function will prepare LIN interface to receive data and then return.
 * Data bytes will be received to the buffer in the interrupt handler of LIN
 * interface.
 * This function returns zero if preparation of receiving data was successful.
 * @param[in] iii LIN interface that is being handled
 * @param[in] response_length Length of response
 * @return Zero for success
 * @return Non-zero for error
 */
l_u8 lin_lld_rx_response(l_ifc_handle iii,
                         l_u8 response_length);

/*!
 * @brief Callback function for Timer Interrupt Handler
 * In timer IRQ handler, call this function. Used to check if frame timeout has occurred during
 * frame data transmission and reception, to check for N_As and N_Cr timeout for LIN 2.1 and
 * above. This function also check if there is no LIN bus communication (no headers and no frame
 * data transferring) for Idle timeout (s), then put LIN node to Sleep mode. Users may initialize
 * a timer (for example FTM)with period of Timeout unit (default: 500 micro seconds) to call
 * lin_lld_timeout_service().
 * For an interface iii, Idle timeout (s) = max_idle_timeout_cnt * Timeout unit (us)
 * frame timeout (us) = frame_timeout_cnt * Timeout unit (us)
 * N_As timeout (us) = N_As_timeout * Timeout unit (us)
 * N_Cr timeout (us) = N_Cr_timeout * Timeout unit (us)
 * @param[in] iii LIN interface that is being handled
 * @return void
 */
void lin_lld_timeout_service(l_ifc_handle iii);

#endif /* LIN_H */

/*! @} */

/******************************************************************************/
/* EOF */
/******************************************************************************/
